/*
 * @Author: yaoling 1871883713@qq.com
 * @Date: 2022-10-17 10:24:39
 * @LastEditors: yaoling 1871883713@qq.com
 * @LastEditTime: 2022-11-14 19:24:25
 * @FilePath: \company-world\src\apis\request\request.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import axios from 'axios'
import type { AxiosRequestConfig, AxiosInstance, AxiosResponse } from 'axios'
import { ApiDataType } from './type'

// 定义一个Hooks拦截器接口
interface InterceptorHooks {
  // 请求拦截
  requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
  requestInterceptorCatch?: (error: string) => string

  // 响应拦截
  responseInterceptor?: (response: AxiosResponse) => AxiosResponse
  responseInterceptorCatch?: (error: string) => string
}

interface HYRequestConfig extends AxiosRequestConfig {
  interceptorHooks?: InterceptorHooks
}

interface HYData<T> {
  data: T
  returnCode: string
  success: boolean
}

class HYRequest {
  config: AxiosRequestConfig
  interceptorHooks?: InterceptorHooks // Hooks拦截器
  instance: AxiosInstance // 为了保存不同的实例：方便与项目有多个baseURL时

  constructor(options: HYRequestConfig) {
    this.config = options
    this.interceptorHooks = options.interceptorHooks
    this.instance = axios.create(options) // 创建axios实例

    this.setupInterceptor()
  }

  // 使用拦截器
  setupInterceptor(): void {
    // 从config取出的拦截器是对应实例的拦截器
    // 请求拦截
    this.instance.interceptors.request.use(
      this.interceptorHooks?.requestInterceptor,
      this.interceptorHooks?.requestInterceptorCatch
    )
    // 响应拦截
    this.instance.interceptors.response.use(
      this.interceptorHooks?.responseInterceptor,
      this.interceptorHooks?.responseInterceptorCatch
    )
  }

  request<T>(config: HYRequestConfig): Promise<T> {
    return new Promise((resolve, reject) => {
      this.instance
        .request<string, HYData<T>>(config)
        .then((res) => {
          resolve(res.data)
        })
        .catch((err) => {
          reject(err)
        })
    })
  }

  get<T = ApiDataType>(config: HYRequestConfig): Promise<T> {
    return this.request({ ...config, method: 'GET' })
  }

  post<T = ApiDataType>(config: HYRequestConfig): Promise<T> {
    return this.request({ ...config, method: 'POST' })
  }

  delete<T = ApiDataType>(config: HYRequestConfig): Promise<T> {
    return this.request({ ...config, method: 'DELETE' })
  }

  patch<T = ApiDataType>(config: HYRequestConfig): Promise<T> {
    return this.request({ ...config, method: 'PATCH' })
  }

  put<T = ApiDataType>(config: HYRequestConfig): Promise<T> {
    return this.request({ ...config, method: 'PUT' })
  }
}

export default HYRequest
